<template>
    <div class="flow-containers">
        <a-span class="load-spin" :spinning="!fetchLoadEnd" />
        <!-- 头部 -->
        <div class="el-header">
            <div class="el-header-row">
                <!-- 返回 -->
                <a-button @click="handleGOBack">
                    {{ t('back') }}
                </a-button>
                <a-button-group v-if="fetchLoadEnd">
                    <!-- 设置 -->
                    <a-button @click="handleProcessSetting">
                        {{ t('setting') }}
                    </a-button>
                    <!-- 保存 -->
                    <a-button @click="handleSave">
                        {{ t('save') }}
                    </a-button>
                </a-button-group>
            </div>
        </div>
        <!-- 中间部分 -->
        <div class="el-container is-vertical">
            <section class="el-container el-container-content">
                <main class="el-main">
                    <div ref="canvas" class="canvas"></div>
                </main>
                <div class="el-aside">
                    <panel
                        v-if="currentProcessNodeForm"
                        ref="modelerPanel"
                        :modeler="modeler"
                        :fetch-response="fetchResponse"
                        :process-type="processModal.baseForm.processType"
                        :application-id="processModal.baseForm.applicationId"
                        :current-process-node-form="currentProcessNodeForm"
                        :current-modeler-element="currentModelerElement"
                        @selectDataSource="selectDataSource"
                        @processNodeFormChange="handleProcessNodeFormChange"
                    />
                </div>
            </section>
        </div>

        <!-- 新建流程弹框 -->
        <a-modal
            v-model:visible="processVisible"
            :ok-text="t('confirm')"
            :cancel-text="t('cancel')"
            :width="800"
            :centered="true"
            :title="t('base')"
            wrap-class-name="formula-modal"
            @ok="handleSubmitCalculation"
            @cancel="handleCancel"
        >
            <div class="layout-table">
                <a-form
                    ref="processBaseForm"
                    :model="processModal.baseForm"
                    :rules="processModal.baseFormRules"
                    :label-col="processModal.labelCol"
                    :wrapper-col="processModal.wrapperCol"
                >
                    <!-- 所属应用 -->
                    <a-form-item :label="t('applicationId')" name="applicationId">
                        <a-select
                            v-model:value="processModal.baseForm.applicationId"
                            :disabled="true"
                            @select="handleApplicationChange"
                        >
                            <a-select-option
                                v-for="application in fetchResponse.application"
                                :key="application.id"
                                :value="application.id"
                            >
                                {{ application.name }}
                            </a-select-option>
                        </a-select>
                    </a-form-item>
                    <!-- 流程名称 -->
                    <a-form-item :label="t('processName')" name="processName">
                        <a-input v-model:value="processModal.baseForm.processName" />
                    </a-form-item>
                    <!-- 流程类型 -->
                    <a-form-item :label="t('processType')" name="processType">
                        <a-select v-model:value="processModal.baseForm.processType">
                            <a-select-option
                                v-for="typeItem in ProcessType"
                                :key="typeItem.value"
                                :value="typeItem.value"
                            >
                                {{ typeItem.label }}
                            </a-select-option>
                        </a-select>
                    </a-form-item>
                    <!-- 流程描述 -->
                    <a-form-item :label="t('processDescription')" name="processDescription">
                        <a-input v-model:value="processModal.baseForm.processDescription" />
                    </a-form-item>
                </a-form>
            </div>
        </a-modal>
        <!-- 返回是否改变画布内容的保存弹框 -->
        <a-modal
            v-model:visible="backVisible"
            :centered="true"
            :ok-text="t('backOk')"
            :cancel-text="t('backCancel')"
            :confirm-loading="subLoading"
            @cancel="handleReplaceFlow"
            @ok="handleSave"
        >
            <div class="process-back-title">
                {{ t('backTitle') }}
            </div>
            <div class="process-back-text">
                {{ t('backText') }}
            </div>
        </a-modal>
    </div>
</template>

<script lang="ts">
    import { processNodeForm } from '../types/processNodeForm'
    import { modelerElement } from '../types/modeler'

    import customTranslate from './common/customTranslate'
    import flowableModdle from './common/flowable/flowable.json'
    import getInitStr from './common/flowable/init'
    import Modeler from 'bpmn-js/lib/Modeler'
    // 引入flowable的节点文件
    import BpmData from './common/BpmData'
    // 国际化
    import { useI18n } from 'vue-i18n'
    // vue-api
    import { defineComponent, reactive, ref, onMounted, computed, toRaw } from 'vue'
    import panel from './propertyPanel/index.vue'
    import { ProcessType } from '@/enums/commonConstant'
    // 路由导入
    import { useRoute, useRouter } from 'vue-router'
    // api
    import { applicationList, getPublishedPageCategory, fetchPublishPageDetail } from '@/apis/sys/application'
    import { getWorkflowList } from '@/apis/sys/workFlow'
    // 获取应用发布版本历史
    // import { applicationPublishHistory, } from '@/api/applicationList';
    // 工具类
    import { cloneDeep } from 'lodash-es'
    import { $each, $getPublishedApplicationId } from '@/utils/common'
    import { isNullOrUnDef, isEmpty } from '@/utils/is'
    import {
        getWorkflowProcessV6,
        saveWorkflowProcessV6,
        addWorkflowProcessV6,
        // 查询用户列表
        getUserSearch,
        // 查询用户组列表
        getUserGroupSearch,
        // 查询部门列表
        getDepartment,
        getRole
    } from '@/apis/sys/workFlow'
    import { ProcessModal, LabelCol, WrapperCol, BaseForm } from '@/types/module/workFlow'
    import { message } from 'ant-design-vue'
    // vuex
    import { useUserStore } from '@/store/modules/user'
    import type { UserStateWork } from '@/types/module/workFlow'
    import {
        generateProcessNodeForm,
        generateConnectionInfo,
        checkProcessNodeFormList,
        formatProcessNodeForm,
        formatResponseProcessNodeForm
    } from '../utils/processNodeFormUtil'

    export default defineComponent({
        name: 'WorkflowBpmn',
        components: {
            panel
        },
        emits: ['destroyed'],
        setup(_props, { emit }) {
            const route = useRoute()
            const router = useRouter()
            const userStore = useUserStore() as UserStateWork
            /**
             *声明变量部分
             */
            // 国际化
            const { t } = useI18n()
            // 初始化数据是否完毕
            const fetchLoadEnd = ref<boolean>(false)
            let modeler: any = null
            // 加载完表单权限数据的标识, 加载完才能渲染右侧部分, 方便右侧组件渲染变淡权限组件(table)
            const loadPageDetailSuccess = ref<boolean>(false)
            // 请求接口数据
            const fetchResponse = reactive<any>({
                // 应用列表
                application: [],
                // 应用页面列表
                applicationPages: {},
                // 表单配置详情
                pageDetail: [],
                // 用户列表
                userList: [],
                // 用户组列表
                userGroupList: [],
                // 部门列表
                departmentList: [],
                // 角色列表
                roleList: []
            })

            let processModal: ProcessModal<LabelCol, WrapperCol, BaseForm> = reactive({
                labelCol: { span: 4 },
                wrapperCol: { span: 18 },
                baseForm: {
                    // 流程名称
                    processName: '',
                    // 流程类型
                    processType: '',
                    // 流程描述
                    processDescription: '',
                    // 应用id
                    applicationId: '',
                    // 表单id
                    pageId: null
                },
                // 校验字段
                baseFormRules: {
                    processName: [
                        {
                            required: true,
                            message: t('processNameRule'),
                            trigger: 'blur'
                        }
                    ],
                    processType: [
                        {
                            required: true,
                            message: t('processTypeRule'),
                            trigger: 'blur'
                        }
                    ],
                    applicationId: [
                        {
                            required: true,
                            message: t('applicationIdRule'),
                            trigger: 'blur'
                        }
                    ],
                    pageId: [
                        {
                            trigger: 'blur',
                            message: t('pageIdRule'),
                            validator: (_rule, value: string, callbackFun: Function) => {
                                if (value) {
                                    return callbackFun()
                                }
                                callbackFun(t('pageIdRule'))
                            }
                        }
                    ]
                }
            })

            // 已经使用过的表单id列表,用于计算出可以选择的表单名称
            const usedFormIds = ref([])

            // 新建流程弹框-显隐
            const processVisible = ref<boolean>(false)

            // 新建流程的ref元素
            const processBaseForm = ref()

            // 获取panel组件的ref元素
            const modelerPanel = ref()

            // 获取canvas的ref元素
            const canvas = ref()

            let xml = ref<string>('')

            // 查询用户列表-入参
            const userQueryParams = reactive({
                filter: { status: 'NORMAL' },
                pageNo: 1,
                pageSize: 100,
                sort: { field: 'id', direction: 'DESC' }
            })

            // 查询部门-入参
            const departmentQueryParams = reactive({
                filter: { name: '' },
                pageNo: 1,
                pageSize: 100,
                sort: { field: 'id', direction: 'DESC' }
            })

            // 查询用户组列表-入参
            const userGroupQueryParams = reactive({
                filter: { name: '', tenantId: userStore.userInfo?.tenantId },
                pageNo: 1,
                pageSize: 100,
                sort: { field: 'id', direction: 'DESC' }
            })

            // 是否改变画布内容的保存弹框-显隐
            const backVisible = ref<boolean>(false)

            // 提交
            const subLoading = ref<boolean>(false)

            // 流程id
            let queryProcessId = ref()
            // 临时保存
            let cloneProcessModal = {}

            // 所有流程节点的表单列表
            const processNodeFormList = ref<processNodeForm[]>([])
            // 当前选中节点的modeler元素
            const currentModelerElement = ref<modelerElement>()

            // 当前选中的节点表单
            const currentProcessNodeForm = computed(() => {
                const { id } = currentModelerElement.value || {}
                return processNodeFormList.value.find(item => item.processNodeId === id)
            })

            /**
             *方法部分
             */

            function handleProcessNodeFormChange(newProcessNodeForm) {
                const { processNodeId, processNodeName } = newProcessNodeForm

                // 更新节点表单列表中的数据
                const currentProcessNodeIndex = processNodeFormList.value.findIndex(item => {
                    return item.processNodeId === processNodeId
                })
                processNodeFormList.value.splice(currentProcessNodeIndex, 1, newProcessNodeForm)

                // 更新流程图上的节点名称
                const modeling = modeler.get('modeling')
                modeling.updateProperties(toRaw(currentModelerElement.value), { name: processNodeName })
            }

            // 初始化流程数据
            const initModeler = () => {
                // 如果初始化过，无需再次赋值modeler，modeler && loadPageDetailSuccess控制实例modelerPanel
                if (modeler) {
                    return
                }
                modeler = new Modeler({
                    container: canvas.value,
                    additionalModules: [
                        {
                            translate: ['value', customTranslate]
                        }
                    ],
                    moddleExtensions: {
                        flowable: flowableModdle
                    }
                })

                // 给创建的modeler实例绑定事件
                handleBindModelerEvent(modeler)

                // 新增流程定义
                if (!xml.value) {
                    newDiagram()
                } else {
                    createNewDiagram(xml.value)
                }
            }

            function handleBindModelerEvent(modelerInstance) {
                // 添加节点
                modelerInstance.on('shape.added', event => {
                    handleAddProcessNodeForm(event.element)
                })
                // 添加连线
                modelerInstance.on('connection.added', event => {
                    handleAddProcessNodeForm(event.element)
                })
                // 当前选中的元素发生变化
                modelerInstance.on('selection.changed', event => {
                    const [selectedElement] = event.newSelection
                    if (!selectedElement) {
                        return
                    }
                    // 更新当前选中的节点元素
                    currentModelerElement.value = selectedElement
                })
                // 删除节点
                modelerInstance.on('shape.removed', event => {
                    handleRemoveProcessNodeForm(event.element)
                })
                // 删除连线
                modelerInstance.on('connection.removed', event => {
                    handleRemoveProcessNodeForm(event.element)
                })
                // 连线变化
                modelerInstance.on('connection.changed', event => {
                    const { id } = event.element
                    const currentProcessNodeForm = processNodeFormList.value.find(item => {
                        return item.processNodeId === id
                    })
                    if (currentProcessNodeForm) {
                        // 更新当前连线表单上的连线信息
                        const { sourceRef, targetRef } = generateConnectionInfo(event.element)
                        currentProcessNodeForm.sourceRef = sourceRef
                        currentProcessNodeForm.targetRef = targetRef
                    }
                })
                // 元素发生变化
                modelerInstance.on('element.changed', event => {
                    const { id, businessObject } = event.element
                    const currentProcessNodeForm = processNodeFormList.value.find(item => {
                        return item.processNodeId === id
                    })
                    // 如果存在当前节点对应的流程节点表单，则更新其节点名称
                    if (currentProcessNodeForm) {
                        currentProcessNodeForm.processNodeName = businessObject.name
                    }
                })
            }

            // 添加流程节点表单
            function handleAddProcessNodeForm(modelerElement) {
                const { id, type } = modelerElement
                if (['bpmn:Process', 'label'].includes(type)) {
                    return
                }

                // 如果当前节点已经存在，则不再添加节点表单
                const isExistedNode = processNodeFormList.value.find(item => item.processNodeId === id)
                if (isExistedNode) {
                    return
                }

                // 生成一个空的节点表单
                const processNodeForm = generateProcessNodeForm(modelerElement)
                // 生成pageFieldIdList并更新到节点表单上
                processNodeForm.pageFieldIdList = generatePageFieldIdList()
                // 将当前的节点表单加到节点表单列表上
                processNodeFormList.value.push(processNodeForm)
            }

            // 删除流程节点表单
            function handleRemoveProcessNodeForm(modelerElement) {
                const { id } = modelerElement
                // 如果删除的是当前选中的节点，则将当前节点取消选中
                if (currentModelerElement.value?.id === id) {
                    currentModelerElement.value = undefined
                }

                // 将删除的节点对应的表单数据删掉
                const currentProcessNodeFormIndex = processNodeFormList.value.findIndex(item => {
                    return item.processNodeId === id
                })
              currentProcessNodeFormIndex !== -1 && processNodeFormList.value.splice(currentProcessNodeFormIndex, 1)
            }

            const newDiagram = () => {
                createNewDiagram(getInitStr())
            }

            const createNewDiagram = async (data: string) => {
                /**
                 * 将字符串换成图显示出来
                 * data = data.replace(/<!\[CDATA\[(.+?)]]>/g, '&lt;![CDATA[$1]]&gt;')
                 */
                data = data.replace(/<!\[CDATA\[(.+?)]]>/g, (_match, str) => str.replace(/</g, '&gt;'))
                try {
                    await modeler.importXML(data)
                    // 调整左侧工具栏排版
                    adjustPalette()
                } catch (error) {}
            }

            // 调整左侧工具栏排版
            const adjustPalette = () => {
                try {
                    if (canvas.value) {
                        const djsPalette = canvas.value.children[0].children[1].children[5]
                        const djsPalStyle = {
                            width: 'auto',
                            padding: '5px',
                            background: 'white',
                            left: '20px',
                            borderRadius: 0
                        }

                        for (const key in djsPalStyle) {
                            djsPalette.style[key] = djsPalStyle[key]
                        }

                        const palette = djsPalette.children[0]
                        const allGroups = palette.children
                        allGroups[0].style['display'] = 'none'

                        // group容器样式
                        const groupStyle = {
                            display: 'flex',
                            flexDirection: 'column'
                        }

                        // 修改控件样式
                        for (const gKey in allGroups) {
                            const group = allGroups[gKey]

                            // 给group设置样式
                            // 隐藏无用组件
                            setGroupDisable(gKey, allGroups, group, groupStyle)
                            setChildrenStyle(gKey, group)

                            for (const cKey in group.children) {
                                const control = group.children[cKey]

                                // 判断是否是无用组件
                                const controlStyle = {
                                    display: isUselessComponent(Number(gKey), Number(cKey)) ? 'none' : 'flex',
                                    justifyContent: 'flex-start',
                                    alignItems: 'center',
                                    width: 'auto',
                                    padding: '5px'
                                }

                                if (control.className && control.dataset && control.className.indexOf('entry') !== -1) {
                                    const controlProps = new BpmData().getControl(control.dataset.action)

                                    control.innerHTML = `
                  <div style='font-size: 14px;font-weight: 500;margin-left: 15px;'>${controlProps['title']}</div>
                  `
                                    for (const csKey in controlStyle) {
                                        control.style[csKey] = controlStyle[csKey]
                                    }
                                }
                            }
                        }
                    }
                } catch (error) {}
            }

            // 隐藏无用组件
            const setGroupDisable = (gKey, allGroups, group, groupStyle) => {
                // 第4个分组(包含第四个)之后的分组是无用组件
                const number = 4
                for (const key in groupStyle) {
                    // 第一个元素隐藏
                    Number(gKey) && (group.style[key] = groupStyle[key])
                    // 第4个分组(包含第四个)之后的分组是无用组件，隐藏无用组件
                    if (Number(gKey) > number) {
                        allGroups[gKey].style['display'] = 'none'
                    }
                }
            }

            // 给group中的children设置样式
            const setChildrenStyle = (gKey, group) => {
                for (const cKey in group.children) {
                    const control = group.children[cKey]
                    // 判断是否是无用组件
                    const controlStyle = {
                        display: isUselessComponent(Number(gKey), Number(cKey)) ? 'none' : 'flex',
                        justifyContent: 'flex-start',
                        alignItems: 'center',
                        width: 'auto',
                        padding: '5px'
                    }

                    if (control.className && control.dataset && control.className.indexOf('entry') !== -1) {
                        const controlProps = new BpmData().getControl(control.dataset.action)
                        control.innerHTML = `
              <div style='font-size: 14px;font-weight:500;margin-left:15px;'>${controlProps['title']}</div>
            `
                        control.style = Object.assign(control.style, controlStyle)
                    }
                }
            }

            // 判断是不是无用组件
            const isUselessComponent = (gKey, cKey) => {
                // 第三个分组的第一个组件是无用组件，第一个分组的第一个组件是无用组件，gKey是group的下标，cKey是group中的children的下标
                return (gKey === 3 || gKey === 1) && cKey === 1
            }

            // 返回-流程列表
            const handleGOBack = () => {
                if (handleCheckBack()) {
                    handleReplaceFlow()
                    return
                }
                backVisible.value = true
            }

            // 根据输入性筛选
            const filterOption = (input, option) => {
                return option.componentOptions.children[0].text.toUpperCase().indexOf(input.toUpperCase()) >= 0
            }

            // 拿到数据源id,获得页面信息
            const selectDataSource = id => {
                getPageDetail(id, pageInfo => {
                    fetchResponse.pageDetail = pageInfo
                    updatePageFieldIdList()
                })
            }

            // 生成页面字段列表
            function generatePageFieldIdList() {
                const noNeedShowComponent = ['AiContentDivider']
                const filteredPageInfo = fetchResponse.pageDetail.filter(item => {
                    return !noNeedShowComponent.includes(item.componentName)
                })

                return cloneDeep(filteredPageInfo)
            }

            // 更新所有节点表单中的pageFieldIdList字段
            function updatePageFieldIdList() {
                processNodeFormList.value.forEach(item => {
                    item.pageFieldIdList = generatePageFieldIdList()
                })
            }

            // 能不能返回直接返回
            const handleCheckBack = () => {
                return !modelerPanel.value || modelerPanel.value.getChangeCount() === 1
            }

            // 初始化获取所有人员、部门、用户组信息数据
            const handleInitFetchResponse = () => {
                // 查询用户列表
                queryUserList()
                // 查询用户组
                queryUserGroup()
                // 查询部门
                queryDepartmentList()
                queryRoleList()
            }

            // 查询用户列表
            const queryUserList = () => {
                getUserSearch(userQueryParams).then(res => {
                    userQueryParams.pageNo = userQueryParams.pageNo + 1
                    fetchResponse.userList = fetchResponse.userList.concat(res.content)
                    // 如果查询数据时大小等于设置的大小 就继续查询
                    if (res.content.length === userQueryParams.pageSize) {
                        queryUserList()
                    }
                })
            }

            // 查询用户组
            const queryUserGroup = () => {
                getUserGroupSearch(userGroupQueryParams).then(res => {
                    userGroupQueryParams.pageNo = userGroupQueryParams.pageNo + 1
                    fetchResponse.userGroupList = fetchResponse.userGroupList.concat(res.content)

                    // 如果查询数据时大小等于设置的大小 就继续查询
                    if (res.content.length === userGroupQueryParams.pageSize) {
                        queryUserGroup()
                    }
                })
            }

            // 查询部门
            const queryDepartmentList = () => {
                getDepartment(departmentQueryParams).then(res => {
                    departmentQueryParams.pageNo = departmentQueryParams.pageNo + 1
                    fetchResponse.departmentList = fetchResponse.departmentList.concat(res.content)

                    // 如果查询数据时大小等于设置的大小 就继续查询
                    if (res.content.length === departmentQueryParams.pageSize) {
                        queryDepartmentList()
                    }
                })
            }

            const queryRoleList = () => {
                getRole(userStore.userInfo?.tenantId).then(res => {
                    fetchResponse.roleList = res
                })
            }

            // 设置-新建流程编辑弹框 点击流程设置按钮
            const handleProcessSetting = () => {
                if (!processVisible.value && fetchLoadEnd.value) {
                    showProcessVisible()
                }
            }

            // 保存-保存设置的流程部分
            const handleSave = () => {
                handleCheckForm(error => {
                    if (error) {
                        return
                    }

                    // 校验节点表单列表
                    const processNodeListCheckResult = checkProcessNodeFormList(processNodeFormList.value)
                    if (processNodeListCheckResult.error) {
                        message.error(processNodeListCheckResult.msg)
                        return
                    }

                    const parameterData = {
                        // 流程名称
                        processName: processModal.baseForm.processName,
                        // 流程配置（xml）
                        processConfig: '',
                        //  流程类型(编码
                        processType: processModal.baseForm.processType,
                        // 应用id
                        applicationId: processModal.baseForm.applicationId,
                        // 应用描述
                        processDescription: processModal.baseForm.processDescription,
                        // 表单id
                        pageId: processModal.baseForm.pageId,
                        processNodeList: []
                    }

                    subLoading.value = true

                    // 获取流程图绘图信息
                    modeler.saveXML({ format: true }).then(res => {
                        const { xml: processConfig } = res
                        // 给请求参数添加流程图绘图信息
                        parameterData.processConfig = processConfig
                        // 给请求参数添加节点表单信息
                        parameterData.processNodeList = formatProcessNodeForm(processNodeFormList.value)

                        // 是不是修改 还是新建
                        if (queryProcessId.value) {
                            saveWorkflowProcessV6(queryProcessId.value, parameterData)
                                .then(() => {
                                    message.success(t('success'))
                                    modelerPanel.value.setChangeCount(1)
                                    backVisible.value = false
                                })
                                .finally(() => {
                                    subLoading.value = false
                                })
                        } else {
                            addWorkflowProcessV6(parameterData)
                                .then(workflowId => {
                                    message.success(t('addSuccess'))
                                    queryProcessId.value = workflowId
                                    modelerPanel.value.setChangeCount(1)
                                    backVisible.value = false
                                })
                                .finally(() => {
                                    subLoading.value = false
                                })
                        }
                    })
                })
            }

            // 检测表单数据是否检验通过
            const handleCheckForm = checkCall => {
                // 如果是流程详情，并且没有点击过设置
                if (queryProcessId.value && !processBaseForm.value) {
                    checkCall && checkCall()
                    return
                }
                processBaseForm.value &&
                    processBaseForm.value.validate().then(base => {
                        checkCall && checkCall(!base)
                    })
            }

            // 新建流程-确认提交事件 确认关闭设置弹层
            const handleSubmitCalculation = () => {
                handleCheckForm(error => {
                    if (error) {
                        return
                    }
                    Object.assign(cloneProcessModal, cloneDeep(processModal))
                    loadPageDetailSuccess.value = true
                    handleAfterClose()
                    initModeler()
                })
            }

            // 关闭流程设置弹层
            const handleAfterClose = () => {
                Object.assign(processModal, cloneDeep(cloneProcessModal))
                processVisible.value = false

                // 如果是新建并且关闭了 没有通过就返回到列表页
                if (isNullOrUnDef(queryProcessId.value)) {
                    handleCheckForm(error => {
                        if (error) {
                          handleCancel();
                        }
                    })
                }
            }
            // 新建流程-取消事件
            const handleCancel = () => {
              if (route?.query?.layoutPlanId && route?.query?.settingId) {
                router.replace({ name: `menu_system_${route?.query?.settingId}${route?.query?.layoutPlanId}` })
              } else {
                router.replace({ name: 'flow' })
              }
            }
            // 新建流程弹框-所属应用select变化事件 选中应用发生变化
            const handleApplicationChange = async (value, type, curPageId = null) => {
                // 清除关联id
                if (type !== 'detail') {
                    processModal.baseForm.pageId = null
                }

                processModal.baseForm.applicationId = value
                if (!fetchResponse.applicationPages[value]) {
                    // 1.找出应经使用过得表单
                    const applicationId: string[] = await getUsedFormIds(value, curPageId)
                    // 2.找出全部的表单过滤出还未使用（可以选择的表单）
                    getApplicationPages(value, pages => {
                        fetchResponse.applicationPages[value] = pages.filter(
                            item => !applicationId.includes(item.pageId)
                        )
                    })
                }
            }

            /**
             * 获取已经关联过的表单id列表
             * 如果是修改传入当前表单id curPageId
             * 获取所有的表单，在对已使用的表单（排除当前流程使用的表单）取差值就是可选择的表单数据
             */
            const getUsedFormIds = async (applicationId, curPageId = null) => {
                if (usedFormIds.value.length) {
                    return usedFormIds.value
                }

                const params = {
                    filter: {
                        applicationId: applicationId
                    },
                    pageSize: 100,
                    pageNo: 1,
                    sort: {
                        field: 'lastModifiedDate',
                        direction: 'DESC'
                    }
                }
                const res = await getWorkflowList(params)
                let pageIdArr = res.content.map(item => item.id)
                if (curPageId) {
                    pageIdArr = pageIdArr.filter(item => item !== curPageId)
                }
                usedFormIds.value = pageIdArr
                return usedFormIds.value
            }

            // 获取应用下的页面列表
            const getApplicationPages = (applicationId, successCallback) => {
                // 构建请求体
                const data = {
                    applicationId: Number(applicationId)
                }
                getPublishedPageCategory(data).then(res => {
                    // 暂时使用开发端页面列表接口
                    const resData = res.data
                    // 解析出所有的页面（舍弃第一层的目录）
                    const formList: Array<string | number> = []
                    $each(resData, (item, _index) => {
                        // 兼容空分类
                        item.pageList && formList.push(...item.pageList)
                    })

                    // 过滤当前表单，赋值给linkageFormList
                    successCallback(formList)
                })
            }

            // 改变了画布中的节点触发的弹框-取消事件,确认离开
            const handleReplaceFlow = (event?: { target: { className: string; nodeName: string } } | undefined) => {
                // 只有点击了返回按钮，或者函数调用才会离开，否则就停留在当前页面
                if (!event || event?.target?.className === 'ant-btn' || event?.target?.nodeName === 'SPAN') {
                    emit('destroyed')
                    handleCancel();
                }
            }

            // 打开流程设置弹框
            const showProcessVisible = () => {
                Object.assign(processModal, cloneDeep(cloneProcessModal))
                processVisible.value = true
            }

            // 获取页面内详情
            const getPageDetail = (id: string, successCallback: Function) => {
                if (processModal.baseForm.processType === 'SYSTEM_MANAGEMENT') {
                    loadPageDetailSuccess.value = true
                    return
                }

                fetchPublishPageDetail(id).then(res => {
                    if (isNullOrUnDef(res)) {
                        message.error(t('processFromDel'))
                        handleReplaceFlow()
                        return
                    }

                    const list: Array<{
                        filedId: string
                        label: string
                        filterColumnName: string
                        type: string
                        visibilityFlag: boolean
                        editableFlag: boolean
                    }> = []
                    res.columnList.forEach((item: any) => {
                        list.push({
                            // 字段Id,与表单提交id保持一致
                            filedId: item.key,
                            label: item.description,
                            filterColumnName: item.key,
                            type: item.type,
                            // TODO: 可见性 这里需要去取表单中该字段的配置 --待完善
                            visibilityFlag: true,
                            // TODO: 可编辑性 这里需要去取表单中该字段的配置 --待完善
                            editableFlag: true
                        })
                    })
                    // 过滤当前表单，赋值给linkageFormList
                    successCallback(list)
                })
            }

            /**
             *生命周期部分
             */
            onMounted(() => {
                queryProcessId.value = route.query.id
                // 如果没有流程id就代表新建
                const params = {
                    pageNo: 1,
                    pageSize: 1,
                    sort: { field: 'id', direction: 'DESC' },
                    filter: {
                        type: 'LOW_CODE_DEVELOPMENT_PLATFORM',
                        applicationId: $getPublishedApplicationId(),
                        name: '',
                        createdDate: { max: null, min: null, type: 'dateTime' },
                        released: '',
                        createdBy: '',
                        modifyState: ''
                    }
                }
                const promiseArr = [applicationList(params)]

                Promise.all(promiseArr).then(async responseData => {
                    const [applicationData] = responseData
                    fetchResponse.application = applicationData.content
                    cloneProcessModal = cloneDeep(processModal)
                    Object.assign(cloneProcessModal, cloneDeep(processModal))

                    // 是否是新建流程，如果url上有id就是编辑
                    if (isNullOrUnDef(queryProcessId.value)) {
                        // 初始化modal信息，用于弹层取消重新赋值
                        ;(cloneProcessModal as ProcessModal<LabelCol, WrapperCol, BaseForm>).baseForm.applicationId =
                            $getPublishedApplicationId()
                        handleApplicationChange($getPublishedApplicationId(), 'detail')
                        fetchLoadEnd.value = true
                        showProcessVisible()
                    } else {
                        getWorkflowProcessV6(queryProcessId.value).then(res => {
                            const detailInfo = res
                            xml.value = detailInfo.processConfig
                            // 重置流程基础 表单数据
                            ;(cloneProcessModal as ProcessModal<LabelCol, WrapperCol, BaseForm>).baseForm = {
                                // 流程名称
                                processName: detailInfo.processName,
                                // 流程类型
                                processType: detailInfo.processType,
                                // 流程描述
                                processDescription: detailInfo.processDescription,
                                // 应用id
                                applicationId: detailInfo.applicationId,
                                // 表单id
                                pageId: detailInfo.pageId
                            }

                            Object.assign(processModal, cloneDeep(cloneProcessModal))
                            // 初始化关联应用表单列表
                            handleApplicationChange(detailInfo.applicationId, 'detail', detailInfo.pageId)

                            // 初始化节点表单列表
                            initProcessNodeFormList(detailInfo.processNodeList)
                            // 初始关联表单详情
                            if (detailInfo.pageId) {
                                getPageDetail(detailInfo.pageId, pageInfo => {
                                    fetchResponse.pageDetail = pageInfo
                                    loadPageDetailSuccess.value = true

                                    // 获取关联表单的信息后，重新初始化一下节点表单列表
                                    initProcessNodeFormList(detailInfo.processNodeList)
                                })
                            } else {
                                fetchResponse.pageDetail = []
                                loadPageDetailSuccess.value = true
                            }

                            initModeler()
                            fetchLoadEnd.value = true
                        })
                    }
                    handleInitFetchResponse()
                })
            })

            // 初始化节点表单列表
            function initProcessNodeFormList(rawProcessNodeFormList) {
                // 格式化获取的节点表单数据：对老数据做兼容等
                const formattedProcessNodeFormList = formatResponseProcessNodeForm(
                    rawProcessNodeFormList,
                    fetchResponse.pageDetail
                )
                // 清空节点表单列表，并给其赋获取的新值
                processNodeFormList.value.splice(0)
                processNodeFormList.value.push(...formattedProcessNodeFormList)
            }

            /**
             * 对外暴露部分
             */
            return {
                /**
                 *声明变量部分-暴露
                 */
                // 国际化
                t,
                // 初始化数据是否完毕
                fetchLoadEnd,
                modeler,
                // 加载完表单权限数据的标识, 加载完才能渲染右侧部分, 方便右侧组件渲染变淡权限组件(table)
                loadPageDetailSuccess,
                // 请求接口数据
                fetchResponse,
                processModal,
                // 新建流程弹框-显隐
                processVisible,
                // ProcessType-表单类型（表单流程、系统管理）
                ProcessType,
                // 是否改变画布内容的保存弹框-显隐
                backVisible,
                // 提交
                subLoading,
                // 当前选中流程节点的表单数据
                currentProcessNodeForm,
                // 当前选中的流程节点元素
                currentModelerElement,

                /**
                 * 方法部分
                 */
                // 根据输入性筛选
                filterOption,
                // panel组件的自定义方法
                selectDataSource,
                // 返回
                handleGOBack,
                // 设置
                handleProcessSetting,
                // 保存
                handleSave,
                // 新建流程-确认提交事件
                handleSubmitCalculation,
                // 新建流程-取消事件
                handleCancel,
                // 新建流程弹框-所属应用select变化事件
                handleApplicationChange,
                // 改变了画布中的节点触发的弹框-取消事件
                handleReplaceFlow,
                // 能不能返回直接返回
                handleCheckBack,
                // 处理流程节点表单发生变化的事件
                handleProcessNodeFormChange,
                // ref-DOM元素
                modelerPanel,
                processBaseForm,
                canvas
            }
        }
    })
</script>

<style lang="less">
    /*左边工具栏以及编辑节点的样式*/
    @import '../styles/diagram-js.css';
    @import '../styles/bpmn.css';
    @import '../styles/bpmn-codes.css';
    @import '../styles/bpmn-embedded.css';
    /*左边工具栏以及编辑节点的样式*/
    .flow-containers {
        position: relative;
        width: 100%;
        height: 100%;
        display: flex;
        flex-direction: column;

        // 数据是不是初始化完成
        .load-spin {
            position: absolute;
            width: 100px;
            height: 100px;
            left: 50%;
            top: 50%;
            margin-left: -50px;
            margin-top: -50px;
            z-index: 9;
        }

        // 头部
        .el-header {
            height: auto;
            border-bottom: 1px solid rgb(218, 218, 218);
            padding: 0 20px;
            box-sizing: border-box;
            flex-shrink: 0;

            .el-header-row {
                display: flex;
                padding: 10px 0px;
                justify-content: space-between;
            }
        }

        // 中间部分
        .el-container {
            display: flex;
            flex-direction: row;
            flex: 1;
            flex-basis: auto;
            box-sizing: border-box;
            min-width: 0;
            min-height: 0;

            &-content {
                align-items: stretch;
            }

            &.is-vertical {
                flex-direction: column;
                height: 100%;
            }

            // 不显示中间组件
            .entry.bpmn-icon-intermediate-event-none {
                display: none;
            }
        }

        .el-main {
            display: block;
            -webkit-box-flex: 1;
            -ms-flex: 1;
            flex: 1;
            -ms-flex-preferred-size: auto;
            flex-basis: auto;
            overflow: auto;
            -webkit-box-sizing: border-box;
            box-sizing: border-box;
            padding: 0;

            .canvas {
                width: 100%;
                height: 100%;
            }
        }

        .el-aside {
            overflow: hidden;
            box-sizing: border-box;
            flex-shrink: 0;
            width: 400px;
            min-height: 650px;
            background-color: #fff;
            border-left: 1px solid #e0e0e0;
        }

        // 新建流程弹框

        // 返回是否改变画布内容的保存弹框
        .process-back {
            &-title {
                color: #1f2d3d;
                font-size: 16px;
                line-height: 24px;
                font-weight: 700;
                margin-bottom: 5px;
                margin-top: 3px;
            }

            &-text {
                color: #5e6d82;
                line-height: 24px;
                word-break: break-all;
                word-wrap: break-word;
            }
        }
    }
</style>

<i18n>
zh-CN:
  back: '返回'
  setting: '设置'
  save: '保存'
  backOk: '保存并继续'
  backCancel: '不保存'
  backTitle: '请保存!'
  backText: '请保存!页面跳转后,原先页面未保存的内容将会丢失!'
  confirm: '确定'
  cancel: '取消'
  okText: '确认'
  cancelText: '取消'
  form: '表单关联'
  processName: '流程名称'
  processType: '流程类型'
  processDescription: '流程描述'
  applicationId: '所属应用'
  pageId: '表单名称'
  name: '名称'
  visibility: '可见'
  editable: '可编辑'
  condition: '运算'
  value: '数值'
  processNameRule: '请输入流程名称'
  processTypeRule: '请选择流程类型'
  applicationIdRule: '请选择所属应用'
  pageIdRule: '请选择流程关联表单'
  success: '保存成功'
  addSuccess: '创建成功'
  processFromDel: '该流程关联的表单已经被删除'
  message:
    processName: '请输入流程名称'
    processType: '请选择流程类型'
    applicationId: '请选择所属应用'
    pageId: '请选择流程关联表单'
    success: '保存成功'
    addSuccess: '创建成功'
en-US:
  back: 'back'
  setting: 'setting'
  save: 'save'
  backOk: 'Save and continue'
  backCancel: 'Do not save'
  backTitle: 'Please save!'
  backText: 'Please save! After page Jump, the unsaved content of the original page will be lost!'
  confirm: 'confirm'
  cancel: 'cancel'
  okText: 'confirm'
  cancelText: 'cancel'
  base: 'Basic settings'
  form: 'Form Association'
  processName: 'Process name'
  processType: 'Process type'
  processDescription: 'Process description'
  applicationId: 'Application'
  pageId: 'Form name'
  name: 'name'
  visibility: 'so'
  editable: 'Editable'
  condition: 'operation'
  value: 'numerical value'
  processNameRule: 'Please enter process name'
  processTypeRule: 'Please select a process type'
  applicationIdRule: 'Please select your app'
  pageIdRule: 'Please select a process association form'
  success: 'Saved successfully'
  addSuccess: 'Created successfully'
  processFromDel: 'The form associated with this process has been deleted'
  message:
    processName: 'Please enter process name'
    processType: 'Please select a process type'
    applicationId: 'Please select your app'
    pageId: 'Please select a process association form'
    success: 'Saved successfully'
    addSuccess: 'Created successfully'
</i18n>
